//===============================================================================
// Microsoft patterns & practices
// Mobile Client Software Factory - July 2006
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Mobile.PasswordAuthentication;
using System.Security.Cryptography;
using System.Xml;
using System.IO;
using Microsoft.Practices.Mobile.Configuration;

namespace ConfigSectionEncrypt.Tests
{
	[TestClass]
	public class CryptoTasksFixture
	{
		[TestMethod]
		public void GenerateKeyProducesDifferentKeyEachTime()
		{
			byte[] key1 = CryptoTasks.GenerateKey();
			Assert.IsNotNull(key1);

			byte[] key2 = CryptoTasks.GenerateKey();
			Assert.IsNotNull(key2);

			Assert.IsFalse(CryptographyUtility.CompareBytes(key1, key2));
		}

		[TestMethod]
		public void DecryptedKeyMatchesOriginalKey()
		{
			byte[] key = CryptoTasks.GenerateKey();
			byte[] encryptedKey = CryptoTasks.EncryptKey("test", "test2", key);

			SymmetricAlgorithm algorithm = Rijndael.Create();

			using (RsaAesCryptographyProvider provider = new RsaAesCryptographyProvider("TestContainer"))
			{
				PasswordIdentity identity = new PasswordIdentity("test", "test2", provider);
				CryptographyBlock block = new CryptographyBlock(algorithm, identity.CryptoKey);
				byte[] decryptedKey = block.Decrypt(encryptedKey);
				Assert.IsTrue(CryptographyUtility.CompareBytes(key, decryptedKey));
			}
		}

		[TestMethod]
		public void EncryptedKeyIsDifferentEachTime()
		{
			byte[] key = CryptoTasks.GenerateKey();
			byte[] encryptedKey1 = CryptoTasks.EncryptKey("test", "test2", key);
			byte[] encryptedKey2 = CryptoTasks.EncryptKey("test", "test2", key);
			Assert.IsFalse(CryptographyUtility.CompareBytes(encryptedKey1, encryptedKey2));
		}

		[TestMethod]
		public void EncryptedSectionHasCorrectStartElement()
		{
			byte[] key = CryptoTasks.GenerateKey();
			string section = "<test>This is a test</test>";
			string encryptedSection = CryptoTasks.EncryptSection(section, key);
			Assert.IsTrue(encryptedSection.StartsWith(@"<EncryptedSection name=""test"">"));
		}

		[TestMethod]
		public void EncryptedSectionIsValidXml()
		{
			byte[] key = CryptoTasks.GenerateKey();
			string section = "<test>This is a test</test>";
			string encryptedSection = CryptoTasks.EncryptSection(section, key);
			StringReader reader = new StringReader(encryptedSection);
			XmlReader xml = XmlTextReader.Create(reader);
			while (!xml.EOF && xml.Read())
				;
			xml.Close();
		}

		[TestMethod]
		public void DecryptKeyReturnsOriginalKey()
		{
			byte[] key = CryptoTasks.GenerateKey();
			byte[] encryptedKey = CryptoTasks.EncryptKey("user", "password", key);
			byte[] decryptedKey = CryptoTasks.DecryptKey("user", "password", encryptedKey);

			Assert.IsTrue(CryptographyUtility.CompareBytes(key, decryptedKey));
		}

		[TestMethod]
		public void DecryptSectionReturnsOriginalSection()
		{
			byte[] key = CryptoTasks.GenerateKey();
			string section = "<test>This is a test</test>";
			string encryptedSection = CryptoTasks.EncryptSection(section, key);

			string decryptedSection = CryptoTasks.DecryptSection(encryptedSection, key);
			Assert.AreEqual(section, decryptedSection);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentException))]
		public void DecryptSectionThrowsWhenElementNameIsntCorrect()
		{
			byte[] key = CryptoTasks.GenerateKey();
			string section = "<test>This is a test</test>";
			string encryptedSection = CryptoTasks.EncryptSection(section, key);
			encryptedSection = encryptedSection.Replace("EncryptedSection", "Junk");
			Assert.IsTrue(encryptedSection.StartsWith("<Junk"));

			CryptoTasks.DecryptSection(encryptedSection, key);
		}

		[TestMethod]
		[ExpectedException(typeof(ArgumentException))]
		public void DecryptSectionThrowsIfBadData()
		{
			byte[] key = CryptoTasks.GenerateKey();
			string encryptedSection = @"<EncryptedSection name=""junk"">junk data</EncryptedSection>";
			CryptoTasks.DecryptSection(encryptedSection, key);
		}
	}
}
